<?php
declare (strict_types = 1);

namespace app\api\middleware;

use app\api\services\RabbitMqPublishService;
use Closure;
use think\App;
use think\Request;
use think\Response;

class ApiRequest
{
    /**
     * 处理请求
     * @param Request $request
     * @param Closure $next
     * @return void
     */
    public function handle($request, Closure $next)
    {
        // 记录请求开始时间，用于计算整个请求的执行时间
        $startTime = microtime(true);
        // 生成符合 SkyWalking 规则的 traceid
        $traceId = $this->generateSkyWalkingTraceId();
        // 将 traceid 保存到请求对象中
        $request->traceId = $traceId;

        App::getInstance()->userinfo->setLoginInfo($request);
        $response = $next($request);
        $response->header(['X-Trace-ID' => $traceId]);

        // 请求结束后的操作
        $this->logOperation($request, $response, $startTime);
        return $response;
    }

    public function end(Response $response)
    {
    }

    /**
     * 1066712991248253.58071737.3721.1
     * @return [type]            [description]
     */
    private function generateSkyWalkingTraceId()
    {
        $instanceId = '10';
        $uid        = uniqid($instanceId, true);
        // 生成一个随机序列号
        $sequence = mt_rand(1000, 9999);
        // 假设分片数量为1
        $total = 1;
        // 按照 SkyWalking 规则格式化 traceid
        $traceId = sprintf("%s.%d.%d",
            $uid,
            $sequence,
            $total);

        return $traceId;
    }

    /**
     * 记录操作日志
     * @param  [type]   $request   [description]
     * @param  Response $response  [description]
     * @param  [type]   $startTime [description]
     * @return [type]              [description]
     */
    protected function logOperation($request, Response $response, $startTime)
    {
        // 计算请求处理时间
        $endTime  = microtime(true);
        $duration = $endTime - $startTime;

        $createAt   = date('Y-m-d H:i:s');
        $userId     = \think\App::getInstance()->userinfo->id;
        $geoip      = $request->ip();
        $traceId    = $request->traceId;
        $deviceType = $request->header('Devicetype');
        $deviceId   = $request->header('Deviceid');
        $lng        = $request->header('Lng', ''); // longitude 经度
        $lat        = $request->header('Lat', ''); // latitude 纬度
        // var_dump($lng);exit;
        $referer = $request->server('HTTP_REFERER');
        $api     = $request->url();
        $method  = $request->method();
        $params  = $request->param();
        if (isset($params['payPassword'])) {
            $params['payPassword'] = '';
        }
        if (isset($params['password'])) {
            $params['password'] = '';
        }
        $params = json_encode($params, 320);
        $data   = $response->getData();
        $data2  = $data['data'] ?? [];
        $data2  = is_array($data2) ? $data2 : json_decode(json_encode($data2), true);
        // var_dump($data);exit;
        $token = $data2['token'] ?? '';
        if ($api == '/api/login/login' && ! empty($token)) {
            $payload = \app\common\libs\Jwt::verifyToken($token);
            // var_dump($payload['id']);exit;
            $userId = $payload['id'];
        }

        isset($data['data']) && $data['data'] = 'no_record';

        $resp_code = $response->getCode();
        if ($resp_code == 404) {
            $data = '';
        }
        $opResult = json_encode([
            'resp_code' => $resp_code,
            'resp_data' => $data,
        ], 320);
        $userAgent = $request->header('user-agent');
        $pushData  = [
            'user_id'     => $userId,
            'create_at'   => $createAt,
            'geoip'       => $geoip,
            'lng'         => $lng, // longitude 经度
            'lat'         => $lat, // latitude 纬度
            'trace_id'    => $traceId,
            'device_type' => $deviceType,
            'device_id'   => $deviceId,
            'referer'     => $referer,
            'api'         => str_replace('//', '/', $api),
            'method'      => $method,
            'params'      => $params,
            'duration'    => $duration, // 0.019958019256592
            'op_result'   => $opResult,
            'useragent'   => $userAgent,
        ];
        try {
            // 发送MQ
            RabbitMqPublishService::getInstance()->publish(
                config('rabbitmq.member_oplog'),
                $pushData,
                $inserTest = false
            );
        } catch (\Exception $e) {
            //
        }
    }
}
